﻿using Microsoft.AspNetCore.Http;
using mozhi.smarterp.Finance.Accounts;
using mozhi.smarterp.Finance.Accounts.Repository;
using mozhi.smarterp.Finance.Enums;
using mozhi.smarterp.Finance.Querys;
using Mozhi.Abp.Core.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;

namespace mozhi.smarterp.Finance.Finances.Services.EndPeriodProcess
{
    /// <summary>
    /// 计提折旧期末处理
    /// </summary>
    public class DepreciationEndPeriodProcessor : EndPeriodProcessorBase<AccountBalance>
    {
        public DepreciationEndPeriodProcessor(EndPeriodProcessItem item, int period, IServiceProvider serviceProvider) : base(item, period, serviceProvider)
        {
        }

        protected override async Task LoadCalculationDataAsync()
        {
            var accountBalanceRepository = _serviceProvider.GetService(typeof(IAccountBalanceRepository)) as IAccountBalanceRepository;

            var previousPeriod = _period.ToPrePeriod();

            var depreciationAccountCode = _item?.Settings?.FirstOrDefault(x => x.DefaultAccountCode == "1602")?.CustomAccountCode;

            var account = GetAccount(depreciationAccountCode);

            var filter = new AccountBalanceQuery() { AccountIds = new List<Guid>() { account.Id }, Period = previousPeriod, IncludeCurrency = false, IncludeDimension = false };

            var previousPeriodBalances = await accountBalanceRepository.FindAsync(filter);

            _data = previousPeriodBalances;

            filter.Period = _period;

            var currentPeriodBalances = await accountBalanceRepository.FindAsync(filter);

            _data.AddRange(currentPeriodBalances);
        }

        protected override async Task<EndPeriodProcessResult> HandleDataAsync()
        {
            EndPeriodProcessResult result = null;

            var depreciationAccountCode = _item?.Settings?.FirstOrDefault(x => x.DefaultAccountCode == "1602")?.CustomAccountCode;

            var account = GetAccount(depreciationAccountCode);

            var previousPeriodBalance = _data.FirstOrDefault(x => x.AccountId == account.Id && x.Period == _period.ToPrePeriod() && x.CurrencyId == null && x.DimensionGroupValueId == null);

            var currentPeriodBalance = _data.FirstOrDefault(x => x.AccountId == account.Id && x.Period ==_period && x.CurrencyId == null && x.DimensionGroupValueId == null);


            var currentDepreciationAmount = currentPeriodBalance?.CreditAmount;
            var previousDepreciationAmount = previousPeriodBalance?.CreditAmount;

            result = new EndPeriodProcessResult(_guidGenerator.Create(), _item.Id, _period, Enums.EndPeriodProcessType.Depreciation);

            result.Change(true, false, null, previousDepreciationAmount, false);

            var resultItems = GetResultItems(result.Id , currentDepreciationAmount , previousDepreciationAmount);

            resultItems.ForEach(x =>
            {
                result.AddItem(x);
            });
            
            return result;
        }

        protected override async Task<Journal> HandleGenerateJournalAsync()
        {
            //测算结果
            var measureResult = await GetEndPeriodResultAsync();

            var depreciationAccountCode = _item?.Settings?.FirstOrDefault(x => x.DefaultAccountCode == "1602")?.CustomAccountCode;

            var depreciationAccount = GetAccount(depreciationAccountCode);

            var assetAccountCode = _item?.Settings?.FirstOrDefault(x => x.DefaultAccountCode == "560205" || x.DefaultAccountCode == "660205")?.CustomAccountCode;

            var assetAccount = GetAccount(assetAccountCode);

            var amount = measureResult.MeasureValue;

            var journalMananger = _serviceProvider.GetService(typeof(JournalManager)) as JournalManager;

            //按照核算维度进行结转

            var defaultJournalNumberPrefix = await GetJournalDefaultNumberPrefix();

            var journal = await journalMananger.Create(_guidGenerator.Create(), defaultJournalNumberPrefix.Id, _period.ToLastDayDateTime());

            var journalItemDebit = await GetJournalItemAsync("计提折旧", amount ?? 0, assetAccount, null, 0, AccountDirectionType.Debit);

            var journalItemCreadit = await GetJournalItemAsync("计提折旧", amount ?? 0, depreciationAccount, null, 1, AccountDirectionType.Credit);

            journal.ChangeItems(new List<JournalItem>() { journalItemDebit, journalItemCreadit });

            return journal;
        }

        #region
        /// <summary>
        /// 获取子级检查项
        /// </summary>
        /// <param name="incomeAmount"></param>
        /// <param name="carryForwardPercnet"></param>
        /// <param name="finishedGoodsAmount"></param>
        /// <returns></returns>
        private List<EndPeriodProcessResultItem> GetResultItems(Guid resultId, decimal? currentDepreciationAmount, decimal? lastDepreciationAmount)
        {
            var result = new List<EndPeriodProcessResultItem>();

            //设置子处理项
            result.Add(new EndPeriodProcessResultItem(_guidGenerator.Create(), resultId, "本期累计折旧金额", currentDepreciationAmount?.ToString(), 1, 1, false));

            result.Add(new EndPeriodProcessResultItem(_guidGenerator.Create(), resultId, "上期累计折旧金额", lastDepreciationAmount?.ToString(), 1, 2, false));

            return result;

        }
        #endregion
    }
}
